package com.doge.walknovel.business.novel.rating

import android.annotation.SuppressLint
import android.os.Bundle
import android.text.InputFilter
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.activityViewModels
import com.doge.wnpro.R
import com.doge.walknovel.business.novel.NovelDetailViewModel
import com.doge.walknovel.business.novel.NovelDetailViewModelFactory
import com.doge.walknovel.business.novel.NovelRefer
import com.doge.walknovel.business.novel.widgets.PostStarView
import com.doge.walknovel.business.reader.menus.ReaderHelper
import com.doge.walknovel.core.BaseDialogFragment
import com.doge.walknovel.core.base.LoadStatus
import com.doge.walknovel.core.base.isRefreshing
import com.doge.wnpro.databinding.DialogFragmentRatingNovelBinding
import com.doge.walknovel.utils.closeKeyBoard
import com.doge.walknovel.utils.getColor
import com.doge.walknovel.utils.setOnClickCallback
import com.doge.walknovel.utils.toast
import kotlin.math.max
import kotlin.math.min

class RatingCommentNovelDialogFragment : BaseDialogFragment() {
    private var innerBinding: DialogFragmentRatingNovelBinding? = null
    private val binding get() = innerBinding!!

    override val hasShadow = true
    private val maxInputLength = 300
    private val viewModel: NovelDetailViewModel by activityViewModels {
        NovelDetailViewModelFactory(novelId, "rating$refer", referId)
    }
    private val light by lazy { ReaderHelper.light }
    private val refer by lazy { arguments?.getString(NovelRefer.EXTRA_REFER)!! }
    private val referId by lazy { arguments?.getInt(NovelRefer.EXTRA_REFER_ID) }
    private val type by lazy { arguments?.getInt(EXTRA_TYPE)!! }
    private val novelId by lazy { arguments?.getInt(EXTRA_NOVEL_ID)!! }
    private val commentId by lazy { arguments?.getInt(EXTRA_COMMENTS_ID)!! }
    private val chapterId by lazy { arguments?.getInt(EXTRA_CHAPTER_ID)!! }
    private val inputText by lazy { arguments?.getString(EXTRA_INPUT_TEXT) }
    private val stars by lazy { arrayOf(binding.star1, binding.star2, binding.star3, binding.star4, binding.star5) }
    private var inputListener: TextWatcher? = null
    private var inputScore: Int? = null
    private var inputValue: String? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        innerBinding =
            innerBinding ?: DialogFragmentRatingNovelBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initialViews()
        updateByLight()
        inputText?.let { binding.input.setText(it) }
        binding.input.setSelection(binding.input.text.length)
        if (type == TYPE_NOVEL) {
            viewModel.bookDetail.observe(viewLifecycleOwner) { info ->
                stars.forEach { it.isVisible = info.scoreFlag != 1 }
                binding.title.text =
                    getString(if (info.scoreFlag != 1) R.string.rate_this_book else R.string.comment_on_this_book)
            }
        } else if (type == TYPE_CHAPTER) {
            stars.forEach { it.isVisible = false }
            binding.title.text = getString(R.string.comment_on_this_chapter)
        } else if (type == TYPE_COMMENTS) {
            stars.forEach { it.isVisible = false }
            binding.title.text = getString(R.string.reply_to_this_comment)
        }

        viewModel.createLoading.observe(viewLifecycleOwner) {
            binding.postLoading.isVisible = it.isRefreshing()
            if (it == LoadStatus.SUCCESS) {
                toast(R.string.comment_posted)
                dismissAllowingStateLoss()
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun initialViews() {
        binding.input.filters = arrayOf(InputFilter.LengthFilter(maxInputLength))
        inputListener = binding.input.doAfterTextChanged {
            binding.limit.text = "${it?.trim()?.length ?: 0}/$maxInputLength"
            inputValue = it?.toString()
        }
        binding.close.setOnClickCallback { dismissAllowingStateLoss() }
        binding.star1.setOnClickCallback { updateScore(2) }
        binding.star2.setOnClickCallback { updateScore(4) }
        binding.star3.setOnClickCallback { updateScore(6) }
        binding.star4.setOnClickCallback { updateScore(8) }
        binding.star5.setOnClickCallback { updateScore(10) }
        binding.post.setOnClickCallback { post() }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        inputListener?.let { binding.input.removeTextChangedListener(it) }
        binding.close.setOnClickListener(null)
        binding.star1.setOnClickListener(null)
        binding.star2.setOnClickListener(null)
        binding.star3.setOnClickListener(null)
        binding.star4.setOnClickListener(null)
        binding.star5.setOnClickListener(null)
        binding.post.setOnClickListener(null)
        innerBinding = null
    }

    private fun updateScore(point: Int) {
        val value = max(0, min(10, point))
        inputScore = value
        binding.star1.set(if (point < 2) PostStarView.NONE else PostStarView.FILL)
        binding.star2.set(if (point < 4) PostStarView.NONE else PostStarView.FILL)
        binding.star3.set(if (point < 6) PostStarView.NONE else PostStarView.FILL)
        binding.star4.set(if (point < 8) PostStarView.NONE else PostStarView.FILL)
        binding.star5.set(if (point < 10) PostStarView.NONE else PostStarView.FILL)
    }

    private fun post() {
        closeKeyBoard()
        val userInputText = inputValue?.trim()
        if (userInputText == null || userInputText.length < 10 || userInputText.length > 300) {
            toast(R.string.review_should_be_10_300_characters)
            return
        }
        when (type) {
            TYPE_NOVEL -> viewModel.requestSubmitNovelComments(userInputText, inputScore)
            TYPE_COMMENTS -> viewModel.requestSubmitReplyComments(commentId, userInputText)
            TYPE_CHAPTER -> viewModel.requestSubmitChapterComments(userInputText)
        }
    }

    private fun updateByLight() {
        if (light) {
            binding.root.setBackgroundResource(R.drawable.shape_ffffff_20_top)
            binding.title.setTextColor(getColor("#333333"))
            binding.close.setBackgroundResource(R.drawable.ripple_19000000_borderless)
            binding.input.setHintTextColor(getColor("#999999"))
            binding.input.setTextColor(getColor("#333333"))
            binding.limit.setTextColor(getColor("#666666"))
            binding.post.setBackgroundResource(R.drawable.ripple_pink_button)
            binding.postImage.setImageResource(R.mipmap.comments_send_white)
            binding.line.setBackgroundColor(getColor("#E5E5E5"))
            binding.underline.setBackgroundColor(getColor("#E5E5E5"))
        } else {
            binding.root.setBackgroundResource(R.drawable.shape_222222_20_top)
            binding.title.setTextColor(getColor("#AAFFFFFF"))
            binding.close.setBackgroundResource(R.drawable.ripple_33ffffff_borderless)
            binding.input.setHintTextColor(getColor("#AAD0D0D0"))
            binding.input.setTextColor(getColor("#AAffffff"))
            binding.limit.setTextColor(getColor("#AAD0D0D0"))
            binding.post.setBackgroundResource(R.drawable.ripple_black_button)
            binding.postImage.setImageResource(R.mipmap.reader_comments_send_gray)
            binding.line.setBackgroundColor(getColor("#AAD0D0D0"))
            binding.underline.setBackgroundColor(getColor("#AAD0D0D0"))
        }
    }

    companion object {
        const val TYPE_NOVEL = 1
        const val TYPE_CHAPTER = 2
        const val TYPE_COMMENTS = 3

        private const val EXTRA_TYPE = "type"
        private const val EXTRA_NOVEL_ID = "novelId"
        private const val EXTRA_CHAPTER_ID = "chapterId"
        private const val EXTRA_COMMENTS_ID = "commentId"
        private const val EXTRA_INPUT_TEXT = "inputText"

        fun newInstance(
            type: Int,
            novelId: Int,
            commentId: Int?,
            chapterId: Int?,
            inputText: String?,
            refer: String, referId: Int? = null
        ): RatingCommentNovelDialogFragment {
            return RatingCommentNovelDialogFragment().apply {
                arguments = Bundle().apply {
                    putInt(EXTRA_TYPE, type)
                    putInt(EXTRA_NOVEL_ID, novelId)
                    putInt(EXTRA_CHAPTER_ID, chapterId ?: 0)
                    putInt(EXTRA_COMMENTS_ID, commentId ?: 0)
                    putString(EXTRA_INPUT_TEXT, inputText)
                    putString(NovelRefer.EXTRA_REFER, refer)
                    referId?.let { putInt(NovelRefer.EXTRA_REFER_ID, referId) }
                }
            }
        }
    }

}